﻿using Aop.Api.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace Lg.Core.Job
{
    public class Job
    {
        /// <summary>
        /// 所有可执行的任务库，不代表所有任务都会被执行，是否执行取决于 jobList中存在的脚本名称
        /// </summary>
        private static List<JobTask> tasks = new List<JobTask>();
        private static bool stop = true;//job运行状态
        //需要执行的脚本名称
        private static List<string> jobList = new List<string>();
        /// <summary>
        /// 是否已经初始化，避免重复初始化
        /// </summary>
        private static bool IsInit = false;
        private static int delay = 3000;

        public string State { get => stop == false ? "run" : "stop"; }
        /// <summary>
        /// 默认初始化方法，从lgconfig读取脚本配置信息
        /// </summary>
        public static void Init()
        {
            if (!IsInit)
            {
                string filePath =Tools.MapPath(@"\App_Data\LgConfig.xml");
                if (File.Exists(filePath))
                {
                    try
                    {
                        XDocument document = XDocument.Load(filePath);
                        //获取到XML的根元素进行操作
                        XElement job = document.Root!.Element("Job")!;
                        stop = Convert.ToInt32(job.Element("JobState")!.Value) == 0;
                        if (!string.IsNullOrEmpty(job.Element("JobList")!.Value))
                        {
                            jobList = job.Element("JobList")!.Value.Split(',').ToList();
                        }
                        IsInit = true;
                    }
                    catch (Exception e)
                    {
                        throw new Exception($"读取脚本配置信息错误！{e.Message}");
                    }
                }
                else
                {
                    throw new Exception($"未找到脚本配置文件:{filePath}");
                }
            }
            else
            {
                throw new Exception("脚本运行中，不支持再次初始化");
            }

        }
        /// <summary>
        /// 自定义初始化方法
        /// </summary>
        /// <param name="_stop">脚本停止状态，stop</param>
        /// <param name="_tasks"></param>
        /// <param name="_jobList"></param>
        public static void Init(bool _stop = false, List<JobTask>? _tasks = null, params string[] _jobList)
        {
            if (!IsInit)
            {
                stop = _stop;
                if (_tasks != null)
                {
                    tasks.AddRange(_tasks);
                }
                jobList.AddRange(_jobList);
                IsInit = true;
            }
            else
            {
                throw new Exception("脚本运行中，不支持再次初始化");
            }
        }
        /// <summary>
        /// 设置脚本运行时间间隔
        /// </summary>
        /// <param name="_delay"></param>
        public static void SetDelay(int _delay)
        {
            delay = _delay;
        }
        /// <summary>
        /// job尝试启动，当非stop状态的时候才会启动脚本，不管有没有task或joblist都会正常启动脚本，可后期追加脚本任务
        /// </summary>
        public static  void Start()
        {
            if (!stop)
            {
                Task.Run(async () =>
                {
                    Log.Info("job启动", $"首次启动,时间:{DateTime.Now}", "job");
                    while (!stop)
                    {
                        if (tasks.Count > 0 && jobList.Count > 0)
                        {
                            foreach (string str in jobList)
                            {
                                try
                                {
                                    JobTask? task = tasks.Where(p => p.Name == str).FirstOrDefault();
                                    if (task != null && task.State == 0)
                                    {
                                       _= Task.Run(() =>
                                        {
                                            task.State = 1;
                                            task.JobFunction?.Invoke();
                                            task.State = 0;
                                        });
                                    }
                                    else
                                    {
                                        Log.Info($"task启动失败！", $"任务[{task!.Name}],状态:[{task.State}],时间:{DateTime.Now}", "job");
                                    }

                                }
                                catch (Exception e)
                                {
                                    Log.Error($"[{str}]脚本启动异常", e.Message);
                                }
                            }
                            //Log.Info($"Job执行完毕", $"job任务全部执行完毕，3秒后准备启下一轮任务，时间:{DateTime.Now}", "job");
                            await Task.Delay(delay);
                        }

                    }
                });
            }

        }

        /// <summary>
        /// 当脚本关闭后可重新启动脚本
        /// </summary>
        public static void ReStart()
        {
            if (stop)
            {
                stop = false;
                Start();
            }
            else
            {
                throw new Exception("job 运行中不支持重新启动！");
            }
        }
        public static void Stop()
        {
            if (!stop)
            {
                stop = true;
            }
            else
            {
                throw new Exception("job 已经是停止状态！");
            }
        }

        /// <summary>
        /// 判断脚本是否正在运行中
        /// </summary>
        /// <returns></returns>
        public static bool IsRun()
        {
            return stop == false;
        }
        #region [任务管理]
        /// <summary>
        /// 添加脚本事件(无参，无返回值的事件)
        /// </summary>
        /// <param name="name">方法名</param>
        /// <param name="func">委拖方法JobFunction</param>
        public static void AddTask(JobTask task)
        {
            bool hasTask = tasks.Where(p => p.Name == task.Name).Any();
            if (!hasTask)
            {
                tasks.Add(task);
            }
            else
            {
                throw new Exception($"脚本任务已存在同名方法\"{task.Name}\"，不可重复添加!");
            }

        }
        public static void AddTask(List<JobTask> _tasks)
        {
            foreach (var task in _tasks)
            {
                bool hasTask = tasks.Where(p => p.Name == task.Name).Any();
                if (!hasTask)
                {
                    tasks.Add(task);
                }
                else
                {
                    throw new Exception($"脚本任务已存在同名方法\"{task.Name}\"，不可重复添加!");
                }
            }

        }
        public static void AddTask(string name, Action jobFunction, int state = 0)
        {
            tasks.Add(new JobTask()
            {
                Name = name,
                JobFunction = jobFunction,
                State = state
            });
        }
        /// <summary>
        /// 删除脚本事件
        /// </summary>
        /// <param name="name"></param>
        public static void RemoveTask(string name)
        {
            tasks = tasks.Where(p => p.Name != name).ToList();
        }
        /// <summary>
        /// 清空脚本事件库
        /// </summary>
        public static void ClearEvent()
        {
            tasks = new List<JobTask>();
        }
        /// <summary>
        /// 获取脚本库
        /// </summary>
        /// <returns></returns>
        public List<JobTask> GetJobs()
        {
            return tasks;
        }

        /// <summary>
        /// 改变任务运行状态，解决任务异常中止，导至无法重新执行的问题
        /// </summary>
        /// <param name="taskName"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        public static int? ChangeTaskState(string taskName,int state)
        {
            var task = tasks.FirstOrDefault(p => p.Name?.ToLower() == taskName.ToLower());
            if (task != null)
            {
                task.State = state;
                return task.State;
            }
            else
            {
                return null;
            }
        }
        #endregion

      

    }
}
